//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#if _MSC_VER > 1000
#pragma once
#endif

#ifndef __PSEUDOPROCESS_H__
#define __PSEUDOPROCESS_H__

#include <elasys_server.h>
#include <interlocked.h>
#include "pobject.h"

typedef enum ProcessState {
    ProcessState_Unstarted      = 0x00,
    ProcessState_Starting       = 0x01,
    ProcessState_Running        = 0x02,
    ProcessState_Finished       = 0x03,
} ProcessState;

class CPseudoProcess : public PseudoObject, public IProcess
{
public:  // PseudoObject Interface.
    PInterface GetObject() { return (IProcess *) this; }

    Boolean Compare(PVoid pCompareData)
    { return (m_processId == *(ProcessId *)pCompareData) ? TRUE : FALSE; }

public: // IProcess Inteface.

    CARAPI_(PInterface) Probe(
        /* [in]  */ REIID riid);

    CARAPI_(UInt32) AddRef(void);

    CARAPI_(UInt32) Release(void);

    CARAPI Aggregate(
        /* [in] */ AggregateType type,
        /* [in] */ PInterface pObject);

    CARAPI GetDomain(
        /* [out] */ PInterface *ppObject);

    CARAPI Start(
        /* [in] */ WString wsName,
        /* [in] */ WString wsArgs);

    CARAPI Kill();

    CARAPI WaitForExit(
        /* [in] */ Millisecond32 timeout,
        /* [out] */ WaitResult *pResult);

    CARAPI IsAlive(
        /* [out] */ Boolean *pIsAlive);

    CARAPI SetPriorityRank(
        /* [in] */ ThreadPriorityRank priorityRank);

    CARAPI GetPriorityRank(
        /* [out] */ ThreadPriorityRank * pPriorityRank);

    CARAPI SetThreadPoolCapacity(
        /* [in] */ Int32 capacity);

    CARAPI GetThreadPoolState(
        /* [out] */ Int32 * pCapacity,
        /* [out] */ Int32 * pThreads);

    CARAPI GetAllThreads(
        /* [out] */ IObjectEnumerator ** ppThreads);

    CARAPI GetAllModules(
        /* [out] */ IObjectEnumerator ** ppModules);

    CARAPI GetModuleByName(
        /* [in] */ WString name,
        /* [out] */ IModule ** ppModule);

    CARAPI GetModuleByAddress(
        /* [in] */ Address address,
        /* [out] */ IModule ** ppModule);

    CARAPI GetId(
        /* [out] */ ProcessId * pPid);

    CARAPI GetStartInfo(
        /* [out] */ WStringBuf * pName,
        /* [out] */ WStringBuf * pArgs);

    CARAPI GetExitCode(
        /* [out] */ ExitCode * pExitCode);

    CARAPI GetStartTime(
        /* [out] */ SystemTime * pTime);

    CARAPI GetExitTime(
        /* [out] */ SystemTime * pTime);

    CARAPI GetProcessorTimes(
        /* [out] */ Millisecond32 * pUserTime,
        /* [out] */ Millisecond32 * pKernelTime);

    CARAPI GetMemorySizes(
        /* [out] */ Int32 * pPrivateVirtualMemorySize,
        /* [out] */ Int32 * pSharedVirtualMemorySize,
        /* [out] */ Int32 * pPrivatePhysicalMemorySize,
        /* [out] */ Int32 * pSharedPhysicalMemorySize);
public:
    CPseudoProcess(ProcessId processId = -1)
        : m_processId(processId),
          m_hLock(NULL),
          m_pProxy(NULL),
          m_bFinished(FALSE),
          m_priorityRank(ThreadPriorityRank_Normal),
          m_capacity(3) {DLinkNode::Initialize();}

    virtual ~CPseudoProcess();

    ECode Initialize();

private:
    ECode _GetProxy();

private:
    ProcessId    m_processId;
    PVoid        m_hLock;
    IProcess *   m_pProxy;

    Boolean      m_bFinished;

    ThreadPriorityRank m_priorityRank;
    Int32 m_capacity;

private:
    Interlocked m_refs;
};

class CPseudoProcessFactory : public PseudoObjectFactory
{
public:
    ECode CreateObject(
        /* [out] */ PseudoObject ** ppPseudoObject);

    Boolean Compare(
        /* [in] */ PseudoObject * pPseudoObject)
    { return pPseudoObject->Compare((PVoid)&m_processId); }

    PseudoObjectType GetType() { return PseudoObjectType_Process; }

public:
    CPseudoProcessFactory(ProcessId processId) : m_processId(processId) {}

private:
    ProcessId m_processId;
};

#endif // __PSEUDOPROCESS_H__
